package com.ruoyi.common.utils.httpclient.httpclient;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.StatusLine;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.Map.Entry;



@Slf4j
@Component
public class HttpClientHelper {

    @Autowired(required=false)
    private CloseableHttpClient httpClient;

    @Autowired
    @Qualifier("requestConfig")
    private RequestConfig requestConfig;

    @Autowired
    @Qualifier("proxyRequestConfig")
    private RequestConfig proxyRequestConfig;



    public  String sendGet(String url, Map<String, Object> params) throws ParseException, UnsupportedEncodingException, IOException{

        if(params !=null && !params.isEmpty()){

            List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());

            for (String key :params.keySet()){
                pairs.add(new BasicNameValuePair(key, params.get(key).toString()));
            }
            url +="?"+EntityUtils.toString(new UrlEncodedFormEntity(pairs), "UTF-8");
        }
        System.out.println(url);
        HttpGet httpGet = new HttpGet(url);

        CloseableHttpResponse response = httpClient.execute(httpGet);
        int statusCode = response.getStatusLine().getStatusCode();
        if(statusCode !=200){
            httpGet.abort();
            throw new RuntimeException("HttpClient,error status code :" + statusCode);
        }
        HttpEntity entity = response.getEntity();
        String result = null;
        if (entity != null) {
            result = EntityUtils.toString(entity, "utf-8");
            EntityUtils.consume(entity);
            response.close();
            return result;
        }else{
            return null;
        }
    }

    public  String sendGet1(String url, Map<String, Object> params) throws ParseException, UnsupportedEncodingException, IOException{

        if(params !=null && !params.isEmpty()){

            List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());

            for (String key :params.keySet()){
                pairs.add(new BasicNameValuePair(key, params.get(key).toString()));
            }
            url +="?"+EntityUtils.toString(new UrlEncodedFormEntity(pairs), "UTF-8");
        }
        System.out.println(url);
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("User-Agent","ddingnet-3.0");
        CloseableHttpResponse response = httpClient.execute(httpGet);
        int statusCode = response.getStatusLine().getStatusCode();
        if(statusCode !=200){
            httpGet.abort();
            throw new RuntimeException("HttpClient,error status code :" + statusCode);
        }
        HttpEntity entity = response.getEntity();
        String result = null;
        if (entity != null) {
            result = EntityUtils.toString(entity, "utf-8");
            EntityUtils.consume(entity);
            response.close();
            return result;
        }else{
            return null;
        }
    }


    /**带参数的post请求 */
    public String doPost(String url, Map<String, Object> map){
        String result=null;
        //声明httpPost请求
        HttpPost httpPost = new HttpPost(url);
        //加入配置信息
        httpPost.setConfig(requestConfig);
        CloseableHttpResponse httpResponse = null;
        try {
            //判断map是否为空，不为空则进行遍历，封装from表单对象
            if (map != null) {
                List<NameValuePair> list = new ArrayList<NameValuePair>();
                for (Entry<String, Object> entry : map.entrySet()) {
                    list.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
                }
                //构造from表单对象
                UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(list, "UTF-8");
                //把表单放到post里
                httpPost.setEntity(urlEncodedFormEntity);
            }
            //发起请求
            httpResponse = this.httpClient.execute(httpPost);
            //判断是否成功
            if(httpResponse.getStatusLine().getStatusCode()==200){
                result= EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
            }
        }catch (Exception e) {
            log.error("HttpClientHelper.doPost-url : "+ url +", msg : " + e.getMessage());
            httpPost.abort();
        }finally {
            try {
                if (httpResponse != null) {
                    httpResponse.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public String doPostJsonWithProxy(String url,String jsonStr) {
        return doPostJSON(url,jsonStr,null,true);
    }

    public String doPostWithProxy(String url,String jsonStr,HashMap<String, Object> header) {
        return doPostJSON(url,jsonStr,header,true);
    }

    public String doPostSSLJsonWithProxy(String url,String jsonStr) {
        return doPostSSLJSON(url,jsonStr,null,true);
    }


    public String doPostJSON(String url,String jsonStr) {
        return doPostJSON(url,jsonStr,null,false);
    }

    public String doPostJSON(String url,String jsonStr,HashMap<String, Object> header,boolean withProxy) {
        String result = null;
        //创建一个request对象
        HttpPost httpPost = new HttpPost(url);
        //配置连接参数
        if(withProxy){
            log.info("使用代理访问");
            httpPost.setConfig(proxyRequestConfig);
        }else {
            httpPost.setConfig(requestConfig);
        }
        CloseableHttpResponse httpResponse = null;
        try {
            //设置参数
            if (jsonStr != null && !"".equals(jsonStr)) {
                StringEntity entity = new StringEntity(jsonStr, ContentType.APPLICATION_JSON);
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }
            //设置头
            if (header != null && header.size() > 0) {
                for (Entry<String, Object> entry : header.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue().toString());
                }
            }
            //执行request请求
            httpResponse = httpClient.execute(httpPost);
            log.info("code="+httpResponse.getStatusLine().getStatusCode());
            //判断是否成功
            if(httpResponse.getStatusLine().getStatusCode()==200){
                result= EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
            }
        } catch (Exception e) {
            log.error("HttpClientHelper.doPostJSON-url : "+ url +", msg : " + e.getMessage());
            httpPost.abort();
        } finally {
            try {
                if (httpResponse != null) {
                    httpResponse.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
    public String doPostJSONNoEncoding(String url,String jsonStr,HashMap<String, Object> header,boolean withProxy) {
        String result = null;
        //创建一个request对象
        HttpPost httpPost = new HttpPost(url);
        //配置连接参数
        if(withProxy){
            log.info("使用代理访问");
            httpPost.setConfig(proxyRequestConfig);
        }else {
            httpPost.setConfig(requestConfig);
        }
        CloseableHttpResponse httpResponse = null;
        try {
            //设置参数
            if (jsonStr != null && !"".equals(jsonStr)) {
                StringEntity entity = new StringEntity(jsonStr, ContentType.APPLICATION_JSON);
//                entity.setContentEncoding("UTF-8");
//                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }
            //设置头
            if (header != null && header.size() > 0) {
                for (Entry<String, Object> entry : header.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue().toString());
                }
            }
            //执行request请求
            httpResponse = httpClient.execute(httpPost);
            log.info("code="+httpResponse.getStatusLine().getStatusCode());
            //判断是否成功
            if(httpResponse.getStatusLine().getStatusCode()==200){
                result= EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
            }
        } catch (Exception e) {
            log.error("HttpClientHelper.doPostJSON-url : "+ url +", msg : " + e.getMessage());
            httpPost.abort();
        } finally {
            try {
                if (httpResponse != null) {
                    httpResponse.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
    public String doPostSSLJSON(String url,String jsonStr,HashMap<String, Object> header,boolean withProxy) {
        String result = null;
        //创建一个request对象
        HttpPost httpPost = new HttpPost(url);
        //配置连接参数
        if(withProxy){
            log.info("使用代理访问");
            httpPost.setConfig(proxyRequestConfig);
        }else {
            httpPost.setConfig(requestConfig);
        }
        CloseableHttpResponse httpResponse = null;

        CloseableHttpClient cHttpClient = null;
        try {
            //没有用连接池！！！
            cHttpClient = createSSLClientDefault();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        try {
            //设置参数
            if (jsonStr != null && !"".equals(jsonStr)) {
                StringEntity entity = new StringEntity(jsonStr, ContentType.APPLICATION_JSON);
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }
            //设置头
            if (header != null && header.size() > 0) {
                for (Entry<String, Object> entry : header.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue().toString());
                }
            }
            log.info("httpPost="+httpPost.getConfig().toString());
            //执行request请求
            httpResponse = cHttpClient.execute(httpPost);
            log.info("code="+httpResponse.getStatusLine().getStatusCode());
            //判断是否成功
            if(httpResponse.getStatusLine().getStatusCode()==200){
                result= EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
            }
        } catch (Exception e) {
            log.error("HttpClientHelper.doPostJSON-url : "+ url +", msg : " + e.getMessage());
            httpPost.abort();
        } finally {
            try {
                if (httpResponse != null) {
                    httpResponse.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public static CloseableHttpClient createSSLClientDefault() throws Exception{
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy(){
            //信任所有
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        }).build();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
        return HttpClients.custom().setSSLSocketFactory(sslsf).build();
    }

    /**
     * 发送httpPost 表单提交
     * @return
     */
    public String doPost(String url, Map<String,Object> paramMap, String encoding){
        String result = null;
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> paramList = new ArrayList<>();
        Set<String> keySet = paramMap.keySet();
        NameValuePair pair = null;
        for(String key:keySet){
            pair = new BasicNameValuePair(key, paramMap.get(key).toString());
            paramList.add(pair);
        }
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        try {
            httpPost.setConfig(proxyRequestConfig);
            httpPost.setEntity(new UrlEncodedFormEntity(paramList,encoding));
            httpPost.setHeader("charset","UTF-8");
            httpPost.setHeader("Content-Type","application/x-www-form-urlencoded");
            long startTime = System.currentTimeMillis();
            log.info("[HttpClient Post] begin invoke, url:{},params:{}",url,paramList);
            response = httpClient.execute(httpPost);
            long callTime = System.currentTimeMillis() - startTime;
            log.info("[HttpClient Post] end invoke used :"+callTime/1000+" second");
            entity = response.getEntity(); // 获取响应实体
            //打印状态日志
            StatusLine status = response.getStatusLine();
            if(status!=null){
                log.info("[HttpClient Post] return status:"+status.getStatusCode());
            }
            if (null != entity && status.getStatusCode() == 200) {
                result = EntityUtils.toString(entity, encoding);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (Exception e1){
            e1.printStackTrace();
        } finally {
            if(entity != null){
                try {
                    entity.getContent().close();
                } catch (Exception e) {
                    log.error("entity.getContent().close() error",e);
                }
            }
            if(response != null){
                try {
                    response.close();
                } catch (IOException e) {
                    log.error("response.close() error",e);
                }
            }
            httpPost.releaseConnection();
        }
        return result;
    }

}
